package fp.in.scala

/**
  * Created by shichen on 2017/8/21.
  */

class Coffee {
  val price: Double = 0
}

class CreditCard {
  def charge(money: Double): Unit = {
  }
}

/*
object Charge {
  def apply(creditCard: CreditCard,price: Double): Charge = new Charge(creditCard,price)
}
class Charge(cc: CreditCard, double: Double) {

}
*/

case class Charge(creditCard: CreditCard, amount: Double) {
  def combine(other: Charge): Charge = {
    if (creditCard == other.creditCard)
      Charge(creditCard, amount + other.amount)
    else
      throw new Exception("cannot combine charges to different creditcard")
  }
}

class ch01_intro {
  def buyCoffee(cc: CreditCard): Coffee = {
    val coffee = new Coffee()
    cc.charge(coffee.price) //this is not pure, it does processing with the external system
    coffee
  }

  // more functional. has no effect on outside state
  def buyCoffee2(cc: CreditCard): (Coffee,Charge) = {
    val cup = new Coffee()
    (cup,Charge(cc,cup.price))
  }

  def buyCoffees(cc: CreditCard, n: Int): (List[Coffee],Charge) = {
    val purchases: List[(Coffee,Charge)] = List.fill(n)(buyCoffee2(cc))
    val (coffees,charges) = purchases.unzip
    (coffees,charges.reduce((c1,c2) => c1.combine(c2)))
  }

  //为了能够处理多种类型，可以创建参数多态函数
  def findFirst[T](ar: Array[T], f: T => Boolean): Int = {
    @annotation.tailrec
    def loop(n: Int): Int =
      if (n >= ar.length) -1
      else if (f(ar(n))) n
      else loop(n+1)
    loop(0)
  }
}
